package cn.echcz.restboot.auth;

import cn.echcz.restboot.config.JwtProperties;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
@RequiredArgsConstructor
public class JwtHandler {
    @NonNull
    private final JwtProperties jwtProperties;

    public String createAccessTokenByUserId(Integer userId) {
        return createTokenByUserId(userId, jwtProperties.getAccess());
    }

    private String createTokenByUserId(Integer userId, JwtProperties.Item item) {
        JWTCreator.Builder builder = getJwtCreatorBuilder(item);
        builder.withClaim("subject", userId);
        return builder.sign(item.getAlgorithm());
    }

    private JWTCreator.Builder getJwtCreatorBuilder(JwtProperties.Item item) {
        return JWT.create()
                .withIssuer(item.getIssuer())
                .withExpiresAt(new Date(System.currentTimeMillis() + item.getMaxAge()))
                .withClaim("type", item.getType());
    }

    public String createRefreshTokenByUserId(Integer userId) {
        return createTokenByUserId(userId, jwtProperties.getRefresh());
    }

    public Integer getUserIdFromAccessToken(String token) throws JWTVerificationException {
        return getUserIdFromToken(token, jwtProperties.getAccess());
    }

    public Integer getUserIdFromRefreshToken(String token) throws JWTVerificationException {
        return getUserIdFromToken(token, jwtProperties.getRefresh());
    }

    private Integer getUserIdFromToken(String token, JwtProperties.Item item) throws JWTVerificationException {
        DecodedJWT decodedJWT = verifyToken(token, item);
        return decodedJWT.getClaim("subject").asInt();
    }

    private DecodedJWT verifyToken(String token, JwtProperties.Item item) throws JWTVerificationException {
        JWTVerifier jwtVerifier = JWT
                .require(item.getAlgorithm())
                .withIssuer(item.getIssuer())
                .withClaim("type", item.getType())
                .build();
        return jwtVerifier.verify(token);
    }

}
